package com.haoran.dwz.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.haoran.dwz.domain.entities.ShortURL;
import com.haoran.dwz.domain.entities.URLRecycleBin;
import com.haoran.dwz.repository.ShortURLRepository;
import com.haoran.dwz.repository.URLRecycleBinRepository;
import com.haoran.dwz.service.ShortUrlService;

@Service
public class ShortUrlServiceImpl implements ShortUrlService {
	@Autowired
	private ShortURLRepository shortURLRepository;
	@Autowired
	private URLRecycleBinRepository urlRecycleBinRepository;

	@Value("${kye.dwz.address:http://ky9.cn/}")
	public static String dwzAddress;

	/**
	 * 分页查询
	 * 
	 * @param pageable
	 * @return
	 */
	public Page<ShortURL> findByPageable(Pageable pageable) {
		return shortURLRepository.findAll(pageable);
	}

	public Page<ShortURL> findByPageable(ShortURL shortURL, Pageable pageable) {
		Specification<ShortURL> querySpecifi = new Specification<ShortURL>() {
			@Override
			public Predicate toPredicate(Root<ShortURL> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
				List<Predicate> predicates = new ArrayList<>();

				Date startDateTime = shortURL.getStartDateTime();
				Date endDateTime = shortURL.getEndDateTime();
				if (startDateTime != null && endDateTime != null) {
					// 大于或等于传入时间
					Predicate between = cb.and(
							cb.greaterThanOrEqualTo(root.get("lastUsedTime").as(Date.class), startDateTime),
							cb.lessThanOrEqualTo(root.get("lastUsedTime").as(Date.class), endDateTime));
					Predicate time = cb.or(cb.and(cb.isNull(root.get("lastUsedTime").as(Date.class))), between);
					predicates.add(time);
				}
				if (StringUtils.isNotBlank(shortURL.getDwz())) {
					// 模糊查找
					predicates.add(cb.or(cb.like(root.get("dwz").as(String.class), "%" + shortURL.getDwz() + "%"),
							cb.like(root.get("url").as(String.class), "%" + shortURL.getUrl() + "%")));
				}
				// and到一起的话所有条件就是且关系，or就是或关系
				if (predicates.size() > 0) {
					return cb.and(predicates.toArray(new Predicate[predicates.size()]));
				}
				return cb.conjunction();
			}
		};
		return shortURLRepository.findAll(querySpecifi, pageable);
	}

	/**
	 * 接口调用次数
	 */
	public long count() {
		return shortURLRepository.count();
	}

	/**
	 * 最后使用时间查询
	 * 
	 * @param stime
	 *            开始时间
	 * @param etime
	 *            截止时间
	 * @return
	 */
	public List<ShortURL> search(Date stime, Date etime) {
		List<ShortURL> resultList = null;
		Specification<ShortURL> querySpecifi = new Specification<ShortURL>() {
			@Override
			public Predicate toPredicate(Root<ShortURL> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
				List<Predicate> predicates = new ArrayList<>();
				if (stime != null) {
					// 大于或等于传入时间
					predicates.add(cb.greaterThanOrEqualTo(root.get("lastUsedTime").as(Date.class), stime));
				}
				if (etime != null) {
					// 小于或等于传入时间
					predicates.add(cb.lessThanOrEqualTo(root.get("lastUsedTime").as(Date.class), etime));
				}
				// and到一起的话所有条件就是且关系，or就是或关系
				if (predicates.size() > 0) {
					return cb.and(predicates.toArray(new Predicate[predicates.size()]));
				}
				return cb.conjunction();
			}
		};
		resultList = shortURLRepository.findAll(querySpecifi);
		return resultList;
	}

	public ShortURL save(ShortURL entity) {
		return shortURLRepository.save(entity);
	}

	public boolean exists(long id) {
		return shortURLRepository.exists(id);
	}

	public ShortURL findOne(long id) {
		return shortURLRepository.findOne(id);
	}

	public List<ShortURL> findAll() {
		return shortURLRepository.findAll();
	}

	@Transactional
	public void delete(long id, String user) {
		if (shortURLRepository.exists(id)) {
			ShortURL shortURLInfo = shortURLRepository.findOne(id);
			URLRecycleBin entity = URLRecycleBin.Builder.builder(shortURLInfo, user);
			urlRecycleBinRepository.save(entity);
			shortURLRepository.delete(id);
		}
	}

	public ShortURL findByUrl(String url) {
		return shortURLRepository.findByUrl(url);
	}
}